package com.upsuns.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import com.upsuns.util.Constants;

/**
 *@Description:<p>客户端处理器，NIO模型</p>
 *@author 王旭
 *@time 2016年3月17日 下午5:40:34
 */
public class TimeClientHandler implements Runnable {
	
	private int port;
	
	private String host;
	
	private  Selector selector;
	
	private SocketChannel socketChannel;
	
	private volatile boolean isStop;
	
	public TimeClientHandler(String host, int port) {
		this.host = host;
		this.port = port;
		
		try {
			this.selector = Selector.open();
			this.socketChannel = SocketChannel.open();
			this.socketChannel.configureBlocking(false);
			boolean isCon = this.socketChannel.connect(new InetSocketAddress(host, port));
			if(isCon) { //连接成功
				this.socketChannel.register(selector, SelectionKey.OP_READ);
				System.out.println("已连接到服务器");
				sendReq(this.socketChannel);
			}
			else {
				this.socketChannel.register(selector, SelectionKey.OP_CONNECT);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	private void stop() {
		this.isStop = true;
	}

	@Override
	public void run() {
		
		while(!isStop) {
			
			try {
				selector.select();
				Set<SelectionKey> keySet = selector.selectedKeys();
				Iterator<SelectionKey> it = keySet.iterator();
				
				SelectionKey key = null;
				while(it.hasNext()) {
					key = it.next();
					it.remove();
					handleKey(key);
				}
			} catch (IOException e) {
				e.printStackTrace();
				System.exit(1);
			}
		}
		
		if(selector != null) {
			try {
				selector.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	private void handleKey(SelectionKey key) {
		if(!key.isValid())
			return ;
		
		SocketChannel channel = (SocketChannel) key.channel();
		
		if(key.isConnectable()) {
			try {
				if(channel.finishConnect()) {
					channel.register(selector, SelectionKey.OP_READ);
					sendReq(channel);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		if(key.isReadable()) {
			ByteBuffer rBuffer = ByteBuffer.allocate(1024);
			try {
				int rcnt = channel.read(rBuffer);
				rBuffer.flip(); //准备读数据
				if(rcnt <= 0)
					return ;
				byte[] respBytes = new byte[rcnt];
				rBuffer.get(respBytes);
				String resp = new String(respBytes, "utf-8");
				System.out.println("响应信息：" + resp);
				stop();
				key.cancel();
				channel.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void sendReq(SocketChannel channel) throws IOException {
		byte[] req = Constants.TIME_QUERY.getBytes();
		ByteBuffer reqBuffer = ByteBuffer.allocate(req.length);
		
		reqBuffer.put(req);
		reqBuffer.flip();
		channel.write(reqBuffer);
	}
	

}
